from django.conf.urls.defaults import *
from django.views.generic import list_detail
from django.contrib import auth
from django.contrib.auth.decorators import login_required
from django.db.models import Q
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render_to_response
from django.template import RequestContext
from models import Domain
from models import Supermaster
from models import Record
from models import Nameserver
from models import Acl
from models import Cryptokey
from models import Domainmetadata
from forms import RecordForm, RecordViewForm
from forms import DomainForm, DomainViewForm
from forms import NameserverForm, NameserverViewForm
from forms import SupermasterForm, SupermasterViewForm
from forms import AclForm, AclViewForm
from forms import CryptokeyForm, CryptokeyViewForm
from forms import DomainmetadataForm, DomainmetadataViewForm
from helper import up_rfc_serial
import settings
import csv
import datetime
import re

@login_required
def records_csv(request):
	response=HttpResponse(mimetype='text/plain')
	#response['Content-Disposition']='attachement; filename=dns_records.csv'
	writer=csv.writer(response)
	records=Record.objects.all()
	writer.writerow(['domain','name','type','ttl','prio','content'])
	for record in records:
		writer.writerow([record.domain, record.name, record.type, record.ttl, record.prio, record.content])
	return response

@login_required
def current_datetime(request):
	now = datetime.datetime.now()
	return render_to_response('current_datetime.html', {'current_date': now},context_instance=RequestContext(request))

@login_required
def domain_list(request):
	domains = Domain.objects.order_by('name')
	records = Record.objects.order_by('name')
	for domain in domains:
		domain.record_count=0
		for record in records:
			if domain.id == record.domain_id:
				domain.record_count=domain.record_count+1
	return render_to_response('domain_list.html', {'domains': domains},context_instance=RequestContext(request))

@login_required
def search(request):
	query = request.GET.get('q', '')
	if query:
		qset = (
			Q(name__icontains=query) |
			Q(description__icontains=query)
			)
		domains = Domain.objects.filter(qset).distinct()
		qset = (
			Q(name__icontains=query) |
			Q(type__icontains=query) |
			Q(content__icontains=query) |
			Q(description__icontains=query)
			)
		records = Record.objects.filter(qset).distinct()
		qset = (
			Q(name__icontains=query) |
			Q(ip__icontains=query) |
			Q(ipv6__icontains=query)
			)
		nameservers = Nameserver.objects.filter(qset).distinct()
	else:
		domains = []
		records = []
		nameservers = []
	return render_to_response("search.html", {
			"domains": domains,
        	"records": records,
			"nameservers": nameservers,
        	"query": query
    	},
		context_instance=RequestContext(request)
	)

@login_required
def view_domain(request, object_id):
	domain=Domain.objects.get(id=object_id)
	records=domain.record_set.all()
	form=DomainViewForm(instance=domain, display_only=True)
	return render_to_response('dns/domain_detail.html', {'form': form, 'domain': domain, 'records': records},context_instance=RequestContext(request))

@login_required
def search_domain(request):
	query = request.GET.get('q', '')
	if query:
		qset = (
			Q(name__icontains=query) |
			Q(master__contains=query) |
			Q(type__contains=query) |
			Q(account__contains=query) |
			Q(serial__contains=query) |
			Q(default_ttl__contains=query) |
			Q(soa_nameserver__contains=query) |
			Q(admin_mailbox__contains=query) |
			Q(description__icontains=query)
		)
		results=Domain.objects.filter(qset).distinct()
	else:
		results=[]
	return render_to_response('dns/domain_search.html', {'results': results, "query": query}, context_instance=RequestContext(request))

@login_required
def view_record(request, object_id):
	record=Record.objects.get(id=object_id)
	form=RecordViewForm(instance=record, display_only=True)
	return render_to_response('dns/record_detail.html', {'form': form, 'record': record},context_instance=RequestContext(request))

@login_required
def search_record(request):
	query = request.GET.get('q', '')
	if query:
		qset = (
			Q(name__contains=query) |
			Q(type__contains=query) |
			Q(content__contains=query) |
			Q(ttl__contains=query) |
			Q(prio__contains=query) |
			Q(description__icontains=query)
		)
		results=Record.objects.filter(qset).distinct()
	else:
		results=[]
	return render_to_response('dns/record_search.html', {'results': results, "query": query}, context_instance=RequestContext(request))


@login_required
def view_nameserver(request, object_id):
	nameserver=Nameserver.objects.get(id=object_id)
	domains=Domain.objects.filter(nameservers=nameserver.id)
	form=NameserverViewForm(instance=nameserver, display_only=True)
	return render_to_response('dns/nameserver_detail.html', {'form': form, 'nameserver': nameserver, 'domains': domains},context_instance=RequestContext(request))

@login_required
def search_nameserver(request):
	query = request.GET.get('q', '')
	if query:
		qset = (
		Q(name__icontains=query) |
		Q(ip__contains=query) |
		Q(ipv6__contains=query)
		)
		results=Nameserver.objects.filter(qset).distinct()
	else:
		results=[]
	return render_to_response('dns/nameserver_search.html', {'results': results, "query": query}, context_instance=RequestContext(request))


@login_required
def view_supermaster(request, object_id):
	supermaster=Supermaster.objects.get(id=object_id)
	form=SupermasterViewForm(instance=supermaster, display_only=True)
	return render_to_response('dns/supermaster_detail.html', {'form': form, 'supermaster': supermaster},context_instance=RequestContext(request))

@login_required
def search_supermaster(request):
	query = request.GET.get('q', '')
	if query:
		qset = (
			Q(nameserver__icontains=query) |
			Q(ip__contains=query) |
			Q(account__contains=query)
		)
		results=Supermaster.objects.filter(qset).distinct()
	else:
		results=[]
	return render_to_response('dns/supermaster_search.html', {'results': results, "query": query}, context_instance=RequestContext(request))

@login_required
def view_acl(request, object_id):
	acl=Acl.objects.get(id=object_id)
	form=AclViewForm(instance=acl, display_only=True)
	return render_to_response('dns/acl_detail.html', {'form': form, 'acl': acl},context_instance=RequestContext(request))

@login_required
def search_acl(request):
	query = request.GET.get('q', '')
	if query:
		qset = (
			Q(type__icontains=query) |
			Q(key__contains=query)
		)
		results=Acl.objects.filter(qset).distinct()
	else:
		results=[]
	return render_to_response('dns/acl_search.html', {'results': results, "query": query}, context_instance=RequestContext(request))

@login_required
def view_cryptokey(request, object_id):
	cryptokey=Cryptokey.objects.get(id=object_id)
	form=CryptokeyViewForm(instance=cryptokey, display_only=True)
	return render_to_response('dns/cryptokey_detail.html', {'form': form, 'cryptokey': cryptokey},context_instance=RequestContext(request))

@login_required
def search_cryptokey(request):
	query = request.GET.get('q', '')
	if query:
		qset = (
			Q(flags__icontains=query) |
			Q(active__contains=query) |
			Q(content__contains=query)
		)
		results=Cryptokey.objects.filter(qset).distinct()
	else:
		results=[]
	return render_to_response('dns/cryptokey_search.html', {'results': results, "query": query}, context_instance=RequestContext(request))

@login_required
def view_domainmetadata(request, object_id):
	domainmetadata=Domainmetadata.objects.get(id=object_id)
	form=DomainmetadataViewForm(instance=domainmetadata, display_only=True)
	return render_to_response('dns/domainmetadata_detail.html', {'form': form, 'domainmetadata': domainmetadata},context_instance=RequestContext(request))

@login_required
def search_domainmetadata(request):
	query = request.GET.get('q', '')
	if query:
		qset = (
			Q(kind__icontains=query) |
			Q(content__contains=query) 
		)
		results=Domainmetadata.objects.filter(qset).distinct()
	else:
		results=[]
	return render_to_response('dns/domainmetadata_search.html', {'results': results, "query": query}, context_instance=RequestContext(request))


@login_required
def add_record(request):
	"""
	adds a record
	qualifies TXT with double-ticks and everything else with domain if not given
	qualifies hostname with domain.name if not FQDN
	updates domain.serial and the domains SOA record accordingly
	"""
	if request.method == 'POST':
		postrequest=request.POST.copy()
		if request.POST['type'] == 'TXT':
			if not re.search('^"(.*)"$', request.POST['content']):
				postrequest['content']='"' + request.POST['content'] + '"'
		domain=Domain.objects.get(id=request.POST['domain'])
		if request.POST['name'] == '':
			postrequest['name']=domain.name
		elif not re.search(domain.name + '$', request.POST['name'], re.IGNORECASE):
			postrequest['name']=request.POST['name'] + "." + domain.name
		form = RecordForm(postrequest)
		if form.is_valid():
			form.save()
			soa=Record.objects.get(domain=domain, type="SOA")
			domain.serial=up_rfc_serial(str(domain.serial))
			domain.save()
			soa_content="" + str(domain.soa_nameserver) + " " + str(domain.admin_mailbox) +  " " + str(domain.serial) +  " " + str(domain.refresh_ttl) +  " " + str(domain.retry_ttl) +  " " + str(domain.expire_ttl) +  " " + str(domain.minimum_ttl) +  " " + str(domain.default_ttl)
			soa.content=soa_content
			soa.save()
			#return render_to_response('dns/record_list.html',context_instance=RequestContext(request))
			return HttpResponseRedirect('/dns/record/')
	else:
		form = RecordForm()
	return render_to_response('dns/record_form.html', {'form': form},context_instance=RequestContext(request))

@login_required
def edit_record(request, object_id):
	"""
	edits record
	updates domain.serial and the domains SOA record accordingly
	"""
	record=Record.objects.get(pk=object_id)
	domain=record.domain
	if request.method == 'POST':
		form=RecordForm(request.POST, instance=record)
		if form.is_valid():
			form.save()
			soa=Record.objects.get(domain=domain.id, type="SOA")
			domain.serial=up_rfc_serial(str(domain.serial))
			domain.save()
			soa_content="" + str(domain.soa_nameserver) + " " + str(domain.admin_mailbox) +  " " + str(domain.serial) +  " " + str(domain.refresh_ttl) +  " " + str(domain.retry_ttl) +  " " + str(domain.expire_ttl) +  " " + str(domain.minimum_ttl) +  " " + str(domain.default_ttl)
			soa.content=soa_content
			soa.save()
			#return render_to_response('dns/record_list.html', context_instance=RequestContext(request))
			return HttpResponseRedirect('/dns/record/')
	else:
		form=RecordForm(instance=record)
	return render_to_response('dns/record_form.html', {'form': form},context_instance=RequestContext(request))

@login_required
def add_domain(request):
	"""
	This function adds an entry to the domain model and generates record entries
	for SOA and NS for each of its Nameservers.
	TOTEST: automatic delegatation down to our new domain if we're controlling its parent
	"""
	if request.method == 'POST':
		form = DomainForm(request.POST)
		if form.is_valid():
			domain=form.save()
			nameservers=Nameserver.objects.filter(domain=domain.id)
			for nameserver in nameservers:
				ns=Record(
					name=domain.name,
					type="NS",
					content=nameserver.name,
					domain_id=domain.id,
					)
				ns.save()
			soa_content="" + str(domain.soa_nameserver) + " " + str(domain.admin_mailbox) +  " " + str(domain.serial) +  " " + str(domain.refresh_ttl) +  " " + str(domain.retry_ttl) +  " " + str(domain.expire_ttl) +  " " + str(domain.minimum_ttl) +  " " + str(domain.default_ttl)
			soa=Record(
				name=domain.name,
				type="SOA",
				content=str(soa_content),
				domain_id=domain.id,
				)
			soa.save()
			try:
				#TOTEST
				match=re.match('^[a-z0-9\-]+\.([a-z0-9\.\-]+)$', domain.name, re.IGNORECASE)
				parent=match.group(1)
				parent_domain=Domain.objects.get(name=parent)
				if parent_domain:
					for nameserver in nameservers:
						ns=Record(
							name=domain.name,
							type="NS",
							content=nameserver.name,
							domain_id=parent_domain.id
							)
						ns.save()
			except:
				request.user.message_set.create(message="Unable to find parent domain, remember to delegate it yourself.")
			#return render_to_response('dns/domain_list.html',context_instance=RequestContext(request))
			return HttpResponseRedirect('/dns/domain/')
	else:
		form = DomainForm()
	return render_to_response('dns/domain_form.html', {'form': form},context_instance=RequestContext(request))

@login_required
def edit_domain(request, object_id):
	"""
	edits domain
	updates domain.serial and the domains SOA record
	keeps NS records for chosen set of nameservers in order
	"""
	domain=Domain.objects.get(pk=object_id)
	if request.method == 'POST':
		form=DomainForm(request.POST, instance=domain)
		if form.is_valid():
			domain=form.save()
			domain.serial=up_rfc_serial(str(domain.serial))
			domain.save()
			soa=Record.objects.get(domain=domain.id, type="SOA")
			soa_content="" + str(domain.soa_nameserver) + " " + str(domain.admin_mailbox) +  " " + str(domain.serial) +  " " + str(domain.refresh_ttl) +  " " + str(domain.retry_ttl) +  " " + str(domain.expire_ttl) +  " " + str(domain.minimum_ttl) +  " " + str(domain.default_ttl)
			soa.content=soa_content
			soa.save()
			todelete=Record.objects.filter(domain=domain.id, type="NS")
			for delme in todelete:
				delme.delete()
			nameservers=Nameserver.objects.filter(domain=domain.id)
			for nameserver in nameservers:
				ns=Record(
					name=domain.name,
					type="NS",
					content=nameserver.name,
					domain_id=domain.id,
					)
				ns.save()
			#return render_to_response('dns/domain_list.html',{'form': form},context_instance=RequestContext(request))
			return HttpResponseRedirect('/dns/domain/')
	else:
		form=DomainForm(instance=domain)
	return render_to_response('dns/domain_form.html', {'form': form},context_instance=RequestContext(request))

@login_required
def add_nameserver(request):
	"""
	adds a nameserver
	TODO: add glue record to its parent domain if we have it
	"""
	if request.method == 'POST':
		form = NameserverForm(request.POST)
		if form.is_valid():
			form.save()
			#return render_to_response('dns/nameserver_list.html',context_instance=RequestContext(request))
			return HttpResponseRedirect('/dns/nameserver/')
	else:
		form = NameserverForm()
	return render_to_response('dns/nameserver_form.html', {'form': form},context_instance=RequestContext(request))

@login_required
def add_supermaster(request):
	"""
	adds a supermaster
	"""
	if request.method == 'POST':
		form = SupermasterForm(request.POST)
		if form.is_valid():
			form.save()
			#return render_to_response('dns/supermaster_list.html',context_instance=RequestContext(request))
			return HttpResponseRedirect('/dns/supermaster/')
	else:
		form = SupermasterForm()
	return render_to_response('dns/supermaster_form.html', {'form': form},context_instance=RequestContext(request))
